package manager

import (
	"context"
	"github.com/tianjigames/fairy/constants"
	"github.com/tianjigames/fairy/model"
	protos2 "github.com/tianjigames/fairy/protos"
	"github.com/topfreegames/pitaya"
	"github.com/topfreegames/pitaya/logger"
	"sync"
	"sync/atomic"
)

var (
	TeamManager *teamManager
	teamManagerOnce sync.Once
)

type teamManager struct {
	BaseManager
	mapTeams map[int]*model.TeamData
	teamIdBase int32
	lock sync.RWMutex
}

/**
新建一个组队管理器
 */
func NewTeamManager() *teamManager {
	teamManagerOnce.Do(func() {
		TeamManager = &teamManager{
			mapTeams: map[int]*model.TeamData{},
		}
	})
	return TeamManager
}

/**
玩家离开组队
 */
func (p *teamManager) QuitTeam(playerId int) error {
	playerInfo :=  GameServerPlayerManager.GetPlayerInfoByPlayerId(playerId)
	if playerInfo == nil || !playerInfo.IsOnline {
		logger.Log.Debugf("quitTeam Player is offline,playerId:%d",playerId)
		return nil
	}

	team,ok := p.mapTeams[playerInfo.TeamId]
	if !ok {
		logger.Log.Debugf("quitTeam player not in team,playerId:%d",playerId)
		return nil
	}

	member,ok := team.GetMembers()[playerInfo.PlayerId]
	if !ok {
		logger.Log.Debugf("quitTeam team member is nil,playerId:%d",playerId)
		return nil
	}

	err := p.SendTeamResultMsg(playerInfo.PlayerId,int(protos2.TeamOperType_TOT_SELFBEQUIT))
	if err != nil {
		logger.Log.Errorf("[TeamManager] QuitTeam failed,error:%s",err.Error())
		return err
	}

	team.DelMember(playerId)
	playerInfo.TeamId = 0
	if p.checkTeam(team) {//组队被删除了
		err = p.sendTeamDismissMsg(playerId,team.TeamId)
		if err != nil {
			logger.Log.Errorf("[TeamManager] QuitTeam failed,error:%s",err.Error())
			return err
		}
	}

	//给队伍发送玩家退出队伍消息
	for _,tm := range team.GetMembers() {
		err = p.SendTeamResultMsgWithName(tm.PlayerId,int(protos2.TeamOperType_TOT_QUITMEMBER),member.PlayerId,member.Name)
		if err != nil {
			logger.Log.Errorf("[TeamManager] QuitTeam failed,error:%s",err.Error())
			return err
		}
	}

	return nil
}

/**
给组队的某个队员发送消息
 */
func (p *teamManager) SendTeamResultMsg(playerId,totType int) error {
	err := p.SendTeamResultMsgWithName(playerId,totType,0,"")
	if err != nil {
		logger.Log.Errorf("[TeamManager]SendTeamResultMsg failed,error:%s",err.Error())
		return err
	}

	return nil
}

/**
给组队发送消息
 */
func (p *teamManager) SendTeamResultMsgWithName(playerId,totType,targetId int,targetName string) error {
	pInfo := GameServerPlayerManager.GetPlayerInfoByPlayerId(playerId)
	if pInfo == nil || !pInfo.IsOnline {
		return nil
	}

	//获取队伍数据
	team,ok := p.mapTeams[playerId]
	if !ok {
		return nil
	}

	ret := &protos2.WGTeamResult{
		ResultType: int32(totType),
		PlayerId: int32(playerId),
	}

	teamInfo := team.ToTeamInfoBuilder()
	p.setTeamBuildOtherValues(teamInfo)
	ret.TeamInfo = teamInfo
	if targetId > 0 && len(targetName) > 0 {
		ret.TargetId = int32(targetId)
		ret.TargetName = targetName
	}

	err := pitaya.RPCTo(context.Background(),constants.WGTeamResultRoute,pInfo.ServerId,&protos2.GWTeamResultRet{},ret)
	if err != nil {
		logger.Log.Errorf("[TeamManager]SendTeamResultMsgWithName failed,error:%s",err.Error())
		return err
	}

	return nil
}

/**
由于闭环原因 设置其他值
 */
func (p *teamManager) setTeamBuildOtherValues(team *protos2.MsgTeamInfo) {
	if team.TeamMemberList != nil && len(team.TeamMemberList) > 0 {
		for _,member := range team.TeamMemberList {
			if member.IsLansquenet == 1 {
				continue
			}

			pInfo := GameServerPlayerManager.GetPlayerInfoByPlayerId(int(member.GetPlayerId()))
			if pInfo != nil {
				member.PlayerGuid = pInfo.PlayerGuid
			}
		}
	}
}

/**
检查摸个组队是否存在 是否将队伍删除
 */
func (p *teamManager) checkTeam(team *model.TeamData) bool {
	if team == nil {
		return false
	}

	if !team.IsOkTeam() {
		delete(p.mapTeams,team.TeamId)
		return true
	}

	return false
}

/**
发送解散队伍消息
 */
func (p *teamManager) sendTeamDismissMsg(playerId,teamId int) error {
	pInfo := GameServerPlayerManager.GetPlayerInfoByPlayerId(playerId)
	if pInfo == nil || !pInfo.IsOnline {
		return nil
	}

	ret := &protos2.WGTeamDismiss{
		TeamId: int32(teamId),
	}

	err := pitaya.RPCTo(context.Background(),pInfo.ServerId,constants.WGTeamDismissRoute,&protos2.GWTeamDismissRet{},ret)
	if err != nil {
		logger.Log.Errorf("[TeamManager] sendTeamDismisssMsg failed,error:%s",err.Error())
		return err
	}

	return nil
}

/**
创建组队
 */
func (p *teamManager) CreateTeam(msg *protos2.GWCreateTeam) error {
	p.lock.Lock()
	defer p.lock.Unlock()

	playerInfo := GameServerPlayerManager.GetPlayerInfoByPlayerId(int(msg.PlayerId))
	if playerInfo == nil || !playerInfo.IsOnline {
		return nil
	}

	if _,ok := p.mapTeams[playerInfo.PlayerId];ok {
		return nil
	}

	teamId := atomic.AddInt32(&p.teamIdBase,1)
	team := model.NewTeamData(int(teamId),playerInfo.PlayerId)
	p.mapTeams[int(teamId)] = team
	team.AddToMember(int(msg.PlayerId),msg.PlayerName,int(msg.Level),int(msg.Career),int(msg.SexId),int(msg.MaxHp))
	playerInfo.TeamId = team.TeamId
	err := p.SendTeamResultMsg(playerInfo.PlayerId,int(protos2.TeamOperType_TOT_CREATE))
	if err != nil {
		logger.Log.Errorf("[TeamManager] CreateTeam failed,error:%s",err.Error())
		return err
	}
	return nil
}

